﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;

using Warehouse.Service.Data;
using Warehouse.Silverlight.Core.Infrastructure.Events;
using Warehouse.Silverlight.Core.Infrastructure.ViewModels;
using Warehouse.Silverlight.Modules.Main.Models;

namespace Warehouse.Silverlight.Modules.Main.ViewModels
{
    [Export]
    public class ProductSearchViewModel : ViewModel
    {
        private readonly IProductSearchModel _productSearchModel;
        private readonly IEventAggregator _eventAggregator;
        private IEnumerable<Category> _categories;
        private int _selectedCategoryId;

        [ImportingConstructor]
        public ProductSearchViewModel(IProductSearchModel productSearchModel, IEventAggregator eventAggregator)
        {
            _productSearchModel = productSearchModel;
            _eventAggregator = eventAggregator;

            Initialize();
        }

        // Override
        protected override void Initialize()
        {
            this.PropertyChanged += new PropertyChangedEventHandler(ProductSearchViewModel_PropertyChanged);

            SearchParams = new ProductSearchParams();
            SearchParams.PropertyChanged += new PropertyChangedEventHandler(SearchParams_PropertyChanged);

            _productSearchModel.GetCategoriesComplete += new EventHandler<EntityResultsArgs<Category>>(_productSearchModel_GetCategoriesComplete);

            SetCommands();

            _productSearchModel.GetCategoriesAsync();

            _eventAggregator.GetEvent<SearchResultChangedEvent>().Subscribe(ChangeSearchResult);
        }

        public ProductSearchParams SearchParams { get; private set; }

        public IEnumerable<Category> Categories
        {
            get { return _categories; }
            private set
            {
                if (_categories != value)
                {
                    _categories = value;
                    RaisePropertyChanged(() => Categories);
                }
            }
        }

        public int SelectedCategoryId
        {
            get { return _selectedCategoryId; }
            set
            {
                if (_selectedCategoryId != value)
                {
                    _selectedCategoryId = value;
                    RaisePropertyChanged(() => SelectedCategoryId);

                    SearchParams["CategoryId"] = _selectedCategoryId;
                    RaisePropertyChanged(() => SearchParams);
                }
            }
        }

        public DelegateCommand SearchCommand { get; set; }
        public DelegateCommand ResetCommand { get; set; }
        public DelegateCommand PrintCommand { get; set; }
        public DelegateCommand ExportCommand { get; set; }

        #region EventAggregator

        public void ChangeSearchResult(bool newResult)
        {
            if (newResult)
            {
                BusyCounter--;
                SearchParams.SetToLast();
                RaisePropertyChanged(() => SearchParams);
            }
        }

        #endregion

        #region SetCommands

        private void SetCommands()
        {
            SearchCommand = new DelegateCommand(
                () => Search(),
                () => CanSearch());

            ResetCommand = new DelegateCommand(
                () => Reset(),
                () => CanReset());

            PrintCommand = new DelegateCommand(
                () => Print(),
                () => CanPrint());

            ExportCommand = new DelegateCommand(
                () => Export(),
                () => CanExport());
        }

        private void Search()
        {
            BusyCounter++;
            _eventAggregator.GetEvent<SearchParamsChangedEvent>().Publish(SearchParams.ToDictionary());
        }
        private bool CanSearch()
        {
            return IsBusy == false;
        }

        private void Reset()
        {
            ResetSearchParams();
        }
        private bool CanReset()
        {
            return SearchParams.IsDefault == false && IsBusy == false;
        }

        private void Print()
        {
            //
        }
        private bool CanPrint()
        {
            return SearchParams.HasChanges == false && IsBusy == false;
        }

        private void Export()
        {
            //
        }
        private bool CanExport()
        {
            return SearchParams.HasChanges == false && IsBusy == false;
        }

        #endregion

        #region private Helpers

        private void _productSearchModel_GetCategoriesComplete(object sender, EntityResultsArgs<Category> e)
        {
            if (!e.HasError)
            {
                this.Categories = e.Results;
            }
            else
            {
                //AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void ProductSearchViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsBusy":
                    ResetCommand.RaiseCanExecuteChanged();
                    SearchCommand.RaiseCanExecuteChanged();
                    PrintCommand.RaiseCanExecuteChanged();
                    ExportCommand.RaiseCanExecuteChanged();
                    break;
                default:
                    break;
            }
        }

        private void SearchParams_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "IsDefault":
                    ResetCommand.RaiseCanExecuteChanged();
                    break;
                case "HasChanges":
                    SearchCommand.RaiseCanExecuteChanged();
                    PrintCommand.RaiseCanExecuteChanged();
                    ExportCommand.RaiseCanExecuteChanged();
                    break;
                default:
                    break;
            }
        }

        private void ResetSearchParams()
        {
            SearchParams.SetFromDefault();
            RaisePropertyChanged(() => SearchParams);
        }

        #endregion
    }
}
